import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

public class GameClient implements GamePlayerInterface {
	
	static int DEFAULT_PORT = 30416;
	static String DEFAULT_HOST = "localhost";
	static String serverHost;
	static int serverPort;

	static String refGameBoard = "GameBoard";
	private PlayerMovementInfo playerInfo;
	private int myID;
	private MazeGameBoard gameboard;
	protected Coordinates initPosition;

	public GameClient() {
		playerInfo = new PlayerMovementInfo();
	}
	
	public void setID(int id) {
		myID = id;
	}
	
	public int getID() {
		return myID;
	}

	public static void main(String[] args) {
		GameClient gc = new GameClient();
		try {
			UnicastRemoteObject.exportObject(gc, 0);
			serverHost = DEFAULT_HOST;
			serverPort = DEFAULT_PORT;
			if (args.length == 1) {
				serverHost = args[0];
			} else if (args.length >= 2) {
				serverHost = args[0];
				serverPort = Integer.parseInt(args[1]);
			}
			
			System.out.println("Game Client - host " + serverHost + " port " + serverPort);
			Registry registry = LocateRegistry.getRegistry(serverHost, serverPort);
			
			GameboardInterface stub = (GameboardInterface) registry
					.lookup(refGameBoard);
			GameStatusInfo response = stub.ConnectPlayer(gc);
			gc.setID(response.GetPlayerID());
			int id = gc.getID();
			switch (response.GetGameStatus()) {
			case GAME_IDLE:
				System.out
						.println("Game Client " + id +": gameboard idling, waiting for other players (" + gc.initPosition.x + "," + gc.initPosition.y + ")");
				gc.initPosition = new Coordinates(response.GetLastPlayerXCoord(), response.GetLastPlayerYCoord());
				break;
			case GAME_STARTING:				
				gc.initPosition = new Coordinates(response.GetLastPlayerXCoord(), response.GetLastPlayerYCoord());
				System.out
				.println("Game Client " + id +": gameboard starting, waiting for other players at (" + gc.initPosition.x + "," + gc.initPosition.y + ")");
				break;
			case GAME_STARTED:
				System.out
						.println("Game Client : sorry cannot join. gameboard already started, please come back later ");
				System.exit(0);
				break;
			}
		} catch (RemoteException e) {
			e.printStackTrace();
		} catch (NotBoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	@Override
	public void ServerStatusUpdate(GameStatusInfo gameStatusInfo)
			throws RemoteException {
		
		System.out.println("Game Client " + getID() +" received from server: "
				+ gameStatusInfo.GetGameStatus().toString());
		if (gameStatusInfo.GetGameStatus() == GameStatusInfo.GameStatus.GAME_STARTED) {
			gameboard = new MazeGameBoard(gameStatusInfo.GetMapSize(),
					this);
		} else if (gameStatusInfo.GetGameStatus() == GameStatusInfo.GameStatus.GAME_IDLE) {
			if (gameboard != null) {
				gameboard.setEndGame();
				gameboard.endGame(gameStatusInfo.playerTreasureCount);
			}
		}
	}

	public void move(PlayerMovementInfo.Direction drct) {
		Registry registry;
		try {
			registry = LocateRegistry.getRegistry(serverHost, serverPort);
			GameboardInterface stub = (GameboardInterface) registry
					.lookup(refGameBoard);
			//exception here
			playerInfo.direction =  drct;
			PlayerMovementInfo response = stub.RequestMove(playerInfo, myID);
			System.out.println("Server response the move " + drct.toString());
			gameboard.updateGameBoard(response);
			
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NotBoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
